package com.ning.plying.config;

import com.ning.plying.TaskManager;
import com.ning.plying.ThreadPoolTaskGenerator;
import com.ning.plying.constant.DefaultConstants;
import com.ning.plying.core.IScheduleTask;
import com.ning.plying.core.ISchedulerServer;
import com.ning.plying.rule.AssignServerRole;
import com.ning.plying.rule.impl.PollingAssignServerRole;
import com.ning.plying.zookeeper.ScheduleTaskZk;
import com.ning.plying.zookeeper.SchedulerServerZk;
import com.ning.plying.zookeeper.ZkClient;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;

/**
 * @author Ning hopening12@gmail.com
 * @date 2021/10/21 19:18
 */
@Slf4j
@Configuration
@EnableScheduling
@EnableConfigurationProperties({PlyingProperties.class})
public class PlyingAutoConfiguration {

    @Autowired
    private PlyingProperties properties;

    /**
     * 定义 ISchedulerServer对象
     */
    @Bean
    public ISchedulerServer iSchedulerServer() {
        final String rootPath = properties.getZk().getRootPath();
        final String taskPath = rootPath + "/" + DefaultConstants.NODE_TASK;
        final String serverPath = rootPath + "/" + DefaultConstants.NODE_SERVER;
        return new SchedulerServerZk(serverPath, taskPath);
    }

    /**
     * 定义 IScheduleTask 对象
     */
    @Bean
    public IScheduleTask iScheduleTask() {
        final String rootPath = properties.getZk().getRootPath();
        final String taskPath = rootPath + "/" + DefaultConstants.NODE_TASK;
        return new ScheduleTaskZk(taskPath);
    }

    /**
     * 定义 server 选择策略
     */
    @Bean
    @ConditionalOnMissingBean(AssignServerRole.class)
    public AssignServerRole assignServerRole() {
        return new PollingAssignServerRole();
    }

    /**
     * 定义动态任务管理
     */
    @Bean
    public TaskManager taskManager(ZkClient zkClient, AssignServerRole assignServerRole) {
        return new TaskManager(zkClient, assignServerRole);
    }

    /**
     * 定义定时任务生成器 bean 名称必须为 taskScheduler
     */
    @Bean(name = "taskScheduler")
    public ThreadPoolTaskGenerator schedulerTaskManager(IScheduleTask scheduleTask, ISchedulerServer schedulerServer) {
        final ThreadPoolTaskGenerator schedulerTaskManager = new ThreadPoolTaskGenerator(properties.getPoolSize(),
                scheduleTask, schedulerServer);
        schedulerTaskManager.setThreadNamePrefix("PlyingSchedulerPool-");
        return schedulerTaskManager;
    }

    /**
     * 定义 ZkClient 对象
     */
    @Bean
    public ZkClient zkClient(ThreadPoolTaskGenerator taskGenerator) {
        return new ZkClient(properties, taskGenerator);
    }
}
